/**
 * Copyright (C),2011-2012,北京国电通网络技术有限公司.
 * FileName:	global.h
 * Author:		LiuHaifeng
 * Version:		V0.1
 * Date:		2011-11-15
 * Description	This file describes all global data-structure used in all program.very important, it decides the style of program.
 */
/**
 * History:
 * 		Author		date		Version		Description
 * 	  LiuHaifeng  2012-02-20	 V0.4      add freescale macro definition
 * 	  LiuHaifeng  2012-03-19    V1.0.6     modification Version
 */

#ifndef GLOBAL_H_
#define GLOBAL_H_

#include <cstdio>				///printf
#include <stdlib.h>				///exit
#include <pthread.h>			///thread relative
//#include <map>					///map       //charlie delete for compiling issue
#include <semaphore.h>			///sem_t
#include <errno.h>				///errno
#include <cstring>				///strerror
//#include <string>				///string    //charlie delete for compiling issue
#include <assert.h>				///assert()
#include <termios.h>			///B9600
#include <semaphore.h>			///sem_t and relative
#include <stddef.h>				///NULL
#include <sys/time.h>			///gettimeofday()
#include <time.h>               ///convert local time to utc
#include <fcntl.h>				///O_NDELAY/O_NOCTTY/O_RDWR
#include <sys/mman.h>			///shared memory relative

///LED light
//#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "control_contre_led.h"

#include "utils.h"

using namespace std;

//////////////////////////////////DEBUG relative+//////////////////////////////////////////
#define SMARTHOME_DEBUG			///switch for debug condition
#define DEBUG_PC				///debug in PC, make sure you have "SMARTHOME_DEBUG"
//#define DEBUG_SOCKET			///debug in ARM, but only socket can be operated
//#define DEBUG_ARM				///debug in ARM or PPC or other platform, make sure you have "SMARTHOME_DEBUG"
//#define NO_DEBUG_ALL			///no debug info, and use all serial, make sure you have CLOSE "SMARTHOME_DEBUG"
//#define NO_DEBUG_SOCKET		///no debug info, only use serial for socket, make sure you have CLOSE "SMARTHOME_DEBUG"
#define DINAIKE					///safeguard have only 2 bytes, while Media have 4 bytes
//#define BSERIAL1               ///serial1 is 1152000

//#define FREESCALE			  ///switch for freescale model

////////////////////////////////////
#include<android/log.h>
#define TAGTEST "guodian"
#define LOGI(FORM,INFO) __android_log_print(ANDROID_LOG_DEBUG,TAGTEST,FORM,INFO)

#ifdef SMARTHOME_DEBUG
	#define ERROROUT(ERRSTR) \
			{printf(ERRSTR);\
			LOGI("%s",ERRSTR);   \
			if(errno!=0) printf("---%s",strerror(errno));\
			printf("\t file name:%s",__FILE__);\
			LOGI("\t file current line:%d\n",__LINE__); \
			LOGI("\t file name:%s",__FILE__);  \
			printf("\t file current line:%d\n",__LINE__);}
	#define PRINTOUT(FORMAT,INFO) \
			{printf(FORMAT,INFO);printf("\n");LOGI(FORMAT,INFO);}
#else
	#define ERROROUT(ERRSTR)
	#define PRINTOUT(FORMAT,INFO)
#endif
///select database location
#ifdef DEBUG_PC
	#define DATABASENAME 	"/data/local/elec.db"

#else

#ifdef FREESCALE
	#define DATABASENAME 	"/home/elec.db"
#else
	#define DATABASENAME	"/mnt/mmc1/elec.db"
#endif

#endif

///select LED file
#ifdef FREESCALE
	#define LED_STATUS		"/dev/mxs_status_light"
	#define LED_MOD2		"/dev/mxs_mod2_light"
	#define LED_MOD3		"/dev/mxs_mod3_light"
#else
	#define LED_STATUS		"/dev/status_led"
	#define LED_MOD2		"/dev/mod2_led"
	#define LED_MOD3		"/dev/mod3_led"
#endif
///select serial ttyS0/ttySP0
#ifdef FREESCALE
	//#define DEV_TTY_0		"/dev/ttySP0"
	#define DEV_TTY_0		"/dev/ttyAMA1"
	#define DEV_TTY_1		"/dev/ttyAMA1"
	#define DEV_TTY_2		"/dev/ttyAMA1"
	#define DEV_TTY_3		"/dev/ttyAMA1"
#else
	//#define DEV_TTY_0		"/dev/ttyS0"
	#define DEV_TTY_0		"/dev/ttyAMA1"
	#define DEV_TTY_1		"/dev/ttyAMA1"
	#define DEV_TTY_2		"/dev/ttyAMA1"
	#define DEV_TTY_3		"/dev/ttyAMA1"
#endif

//////////////////////////////////global variables/////////////////////////////////////////
#define ELECINTERVAL 	60							///query power from 'socket' frequency,once per 'ELECINTERVAL' minutes.

#define EQUIPMENT_NUM 	50							///equipment number
#define CONTROLCMD_NUM	50							///'down' command number
#define RECVRESULT_NUM	10							///'up'	result from serial number

#define CMD_LENGTH_MIN	23							///min length of control command '#** ** ** ****#**#** **#**#'
#define SENDSERIAL_NUM 	24							///the bytes number of control command send to serial port.--eg:68 a0 a1 a2 a3 a4 a5 68 04 09 55 16  33 33 33 33  33 33 33  cs 16,at most 21
#define RECVDATA_NUM 	20							///the number of data reading from serial--eg:68 a0 a1 a2 a3 a4 a5 68 81 06 43 C3 xx xx xx xx cs 16, at most 18

#define SQLITECMDLEN	200							///the max number byte contained in "cmdStr"---command string--sqlite.cpp

#define RETRY_NUM		3							///if command error, just retry RETRY_NUM times
#define REMOVE_NUM		200							///when > this number, command retry struct will be removed

#define NO_MORE			-1							///if list have no more element, it's 'next' point to this

#define GLOBAL_UPDATE	65536						///update times by 0xffff

#define SHARENAME 		"/data/local/myshm" 				///the name of shared memory.can change!
#define SHARESIZE 		4096				    	///the size of shared memory--4k.

#define RECEIVEDELAY	15							///when receive data from serial, delaytime by ms.---safeguard delay 200ms, other delay 20ms

#define PROVERSION		20120320					///program version year-month-day(2011-06-02)

#define ELECGETINTERVAL	   60*60				   ///define ELEC inquiry time interval
#define ELECGETPOINT       50*60				  ///define ELEC inquiry point time period of interval time
#define YGGLGETINTERVAL    10*60				 ///define active power inquiry time interval
#define YGGLGETPOINT       5*60					///define active power point time period of interval time
#define STORAGETIME    3600*24*30*6            ///longest storage month
#define ALARMTIME  60                         ///longest alarm trigger

#define ELEC_UP_NUM 15
#define ACTIVE_UP_NUM 20
//////////////////////////////////global struct////////////////////////////////////////////
/***listHead
*
* define the list head of 'all kinds of struct' list
***/
struct StListHead
{
	int head;
	int type;										///g_devList.st_empty=0;g_devList.st_equip=1;g_downTask.st_emtpy=2;g_downTask.st_task=3
													///g_downTask.st_timeTask=4;g_downTask.st_DeadTimeTask=5;g_upTask.st_emtpy=6;
													///g_upTask.st_recvList=7;g_upTask.st_safeguardList=8
	sem_t st_sem;
};

/***StControlCmd
*
*define the format to hold WEB-SERVICE's data. We also keep the pointer of this struct in list, then
*it can be used in main_control process
***/
struct StControlCmd
{
	unsigned char typeID[3];						///unique identity of an equipment
	unsigned char cmdType;							///type of command, such as control/inquiry/operation/other
	unsigned char param[2];							///the parameter of control command
	int controlTime;								///command operation time
	unsigned char otherParam:4;						///if have other variables?
	unsigned char priority:4;						///plain:0; modelTask:1;

	unsigned char retryTime:3;						///retry times
	unsigned char needRetry:2;						///0 present normal command; 1 present haven't send out; 2 present send out
	int removeNum;									///see how many times retry struct will be removed

	int next;										///listNode
};

/***StReplyData
*
*define the struct to hold serial's data. We keep the pointer of this struct in list, then
*it can be used in main_control process
***/
struct StReplyData
{
//	int devPos;										///equipment
	union
	{
		struct safeGuard
		{
			bool sendFlag;
			int time;
			unsigned char safeguardAddr[RECVDATA_NUM];
		}safeGuard;									///result, active power（有功功率） or total active power(有功总电量)
	}data;
	int next;										///listNode
};

/***StEquipment
*
*define the struct of device  in memory
***/
struct StEquipment
{
	int typeID;										///unique identity ID of equipment
	int operID;										///command format to serial, just in SMART-device
	unsigned char equipmentID[8];					///socket address or safeguard address correspond to special equipment
	double lastHourElecQuan;						///save last hour's total-power
	unsigned char elecQueryStatus:2;				///see if have inquiried total-power
	unsigned char socketStatus:2;					///socket status, just now present device's status--00 off, 01 on, 02 unknown
	unsigned char firstElec:2;						///see if socket is add in just now
	unsigned char activeQueryStatus:2;				///see if have inquiried active power
	int next;										///listNode
};

/***StEquipList
*
*define the list of device  in memory
***/
struct StEquipList
{
	struct StEquipment	st_equipArray[EQUIPMENT_NUM];	///device array
	struct StListHead	st_equip;						///device list
	struct StListHead	st_empty;						///empty device list
};
/***StDownTask
*
*define the struct of all down-task list, include time-task\task\deadtime-task
***/
struct StDownTask
{
	struct StControlCmd	st_command[CONTROLCMD_NUM];		///we can restore 'CONTROLCMD_NUM' cmd from webservice
	struct StListHead	st_task;						///task operate immediately
	struct StListHead	st_timeTask;					///task operate in some future
	struct StListHead	st_emtpy;						///empty element list
};
/***StUpTask
*
*define the struct of all up-task list, include time-task\task\deadtime-task
***/
struct StUpTask
{
	struct StReplyData	st_recvData[RECVRESULT_NUM];	///we can restore 'RECVST_NUM' data struct buffer received from SERIAL
	struct StListHead 	st_safeguardList;				///list of safeguard received data.
	struct StListHead	st_emtpy;						///empty element list
};
/***StSerialFD
*
*serial3(/dev/ttyS1)--socket；serial4(/dev/ttyS2)--safeguard；
*serial6(/dev/ttyS3)--media;serial5(/dev/ttyS0)--debug port
***/
struct StSerialFD
{
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
	int st_serial0;										///serial5
#elif defined DEBUG_SOCKET
	int st_serial1;										///serial3
#elif defined DEBUG_ARM
	int st_serial1;										///serial3
	int st_serial2;										///serial4
	int st_serial3;										///serial6
#endif
#elif defined NO_DEBUG_SOCKET
	int st_serial1;										///serial3
#elif defined NO_DEBUG_ALL
	int st_serial1;										///serial3
	int st_serial2;										///serial4
	int st_serial3;										///serial6
#endif
};
/***StDataTransmit
*
* define array:CC to webservice/webservice to CC, and some flag
***/
struct StDataTransmit
{
	unsigned char st_sendSerial[SENDSERIAL_NUM];		///the array sent to serial
};

/***StDeadTimeTask
*
* to implement 'inquiry total-power'/'upload total-power to service'
***/
struct StDeadTimeTask
{
	int st_inquiryElec;									///time to inquiry elec total-power
	int st_syncTimeTask;								///synchronous time-task in everyday's 00:00 or small later
	int st_inquiryYGGL;									///time to inquiry active power
};
/***StDelay
*
* to implement 'command' send delay
***/
struct StDelay
{
	struct timeval st_lastSend;							///the time last-instruction
	bool st_smart;										///the object of last-instruction is smart? or not?
};
/***StLED
*
*define the struct of LED show
***/
struct StLED
{
	int st_status;										/// /dev/status_led---power status
	int st_mod2;                                       	/// /dev/mod2_led---serial send
	int st_mod3;									    /// /dev/mod3_led---safeguard received
};
/***StOther
*
* other data
***/
struct StOther
{
	bool st_charToUnsignedFlag;							///used in function 'charToUnsigned()' in utils.cpp
	char *st_pCmdOther;									///position of command other variables
	int st_shmFD;										///file descriptor of shared memory
	char *st_shmADDR;									///started address of shared memory
	int st_homeID;										///family identification
};

enum{com_normal,com_waitRetry,com_havRetry};												///used in retry format
enum{equ_yes,equ_no};																		///see if socket first added
enum{sta_no,sta_have};																		///status if have inquiry total-power/active power
enum{sta_off,sta_on,sta_unknown};															///device's status
enum{prio_retry,prio_inquiryElec,prio_timetask,prio_nomal,prio_modeltask};					///priority
enum{find_typeID,find_operID,find_socketID,find_safeguardID};								///used in 'findByID(int ID,int type)'
enum{StEquipList_empty,StEquipList_equip,StDownTask_emtpy,StDownTask_task,StDownTask_timeTask,StUpTask_emtpy,StUpTask_safeguardList};
enum{shm_CLEAR,shm_WRITEDNO,shm_WRITED,shm_SWRITED,shm_RESULT,shm_DISPOSE,shm_ALARM,shm_DEVLIST,shm_TIME,shm_CMD,shm_BEALARM,shm_UPGRADE,shm_UPRESPOND,shm_STATUS};
enum{send_only,err_no,err_timeout,err_format,err_formatpro,err_socket,err_database,err_memory,err_serial,err_other};///error types
//#define WRITEDNO	1								///have copy command from webservice to shared memory--no result
//#define WRITED	2								///have copy command from webservice to shared memory--require result
//#define CLEAR		0								///shared memory is clear
//#define RESULT	3								///result have writed into shared memory
//////////////////////////////////global function//////////////////////////////////////////
#define setResult() (g_other.st_shmADDR[0]=shm_RESULT)
#define clearFlag() (g_other.st_shmADDR[0]=shm_CLEAR)
#define dispose() (g_other.st_shmADDR[0]=shm_DISPOSE)
#define inDispose() (g_other.st_shmADDR[0]==shm_DISPOSE)
#define isSet() (g_other.st_shmADDR[0]==shm_WRITED || g_other.st_shmADDR[0]==shm_WRITEDNO || g_other.st_shmADDR[0]==shm_SWRITED || g_other.st_shmADDR[0]==shm_CMD)
#define haveWRES() (g_other.st_shmADDR[0]==shm_WRITED || g_other.st_shmADDR[0]==shm_WRITEDNO)
#define haveSRES() (g_other.st_shmADDR[0]==shm_SWRITED)
#define noRES() (g_other.st_shmADDR[0]==shm_WRITEDNO)
#define isClear() (g_other.st_shmADDR[0]==shm_CLEAR)
#define setDevList() (g_other.st_shmADDR[0]=shm_DEVLIST)
#define isDevList() (g_other.st_shmADDR[0]==shm_DEVLIST)
#define setTimeFlag() (g_other.st_shmADDR[0]=shm_TIME)
#define isTimeFlag() (g_other.st_shmADDR[0]==shm_TIME)
#define setCMDFlag() (g_other.st_shmADDR[0]=shm_CMD)
#define isCMDFlag() (g_other.st_shmADDR[0]==shm_CMD)
#define setAlarm() (g_other.st_shmADDR[0]=shm_ALARM)
#define isAlarm() (g_other.st_shmADDR[0]==shm_ALARM)
#define setBEAlarm() (g_other.st_shmADDR[0]=shm_BEALARM)
#define isBEAlarm() (g_other.st_shmADDR[0]==shm_BEALARM)
#define isUpGrade() (g_other.st_shmADDR[0]==shm_UPGRADE)
#define setUpRespond() (g_other.st_shmADDR[0]=shm_UPRESPOND)
#define setOptStatus() (g_other.st_shmADDR[0]=shm_STATUS)
#define isOptStatus() (g_other.st_shmADDR[0]==shm_STATUS)

int globalInit();

#endif
